package display.tabs;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import structs.adoption.Adoption;
import structs.term.Term;
import structs.term.dept.Department;
import structs.term.dept.Department.Code;
import structs.term.dept.course.Course;
import structs.term.dept.course.section.Section;
import display.AdoptionImport;
import display.InventoryData;

public class AdoptionTab extends Tab {

	private JTable adoptionTable;
	private JComboBox termBox;
	private Department curDept;
	private Course curCourse;
	private Section curSection;
	private AdoptionActionListener aal = new AdoptionActionListener();
	private CourseSectionTree tree;
	private JScrollPane deptScroll;

	/**
	 * Create the frame.
	 */
	public AdoptionTab(InventoryData in) {
		super(in);

		setBounds(100, 100, 814, 472);
		setBorder(new EmptyBorder(5, 5, 5, 5));
		GridBagLayout gbl_contentPane = new GridBagLayout();
		gbl_contentPane.columnWidths = new int[] { 100, 300, 300, 0 };
		gbl_contentPane.rowHeights = new int[] { 23, 0, 0, 0 };
		gbl_contentPane.columnWeights = new double[] { 1.0, 2.0, 2.0,
				Double.MIN_VALUE };
		gbl_contentPane.rowWeights = new double[] { 0.0, 0.0, 1.0,
				Double.MIN_VALUE };
		setLayout(gbl_contentPane);

		JButton massImport = new JButton("Import");

		massImport.addActionListener(aal);

		GridBagConstraints gbc_massImport = new GridBagConstraints();
		gbc_massImport.insets = new Insets(0, 0, 5, 5);
		gbc_massImport.anchor = GridBagConstraints.NORTH;
		gbc_massImport.fill = GridBagConstraints.HORIZONTAL;
		gbc_massImport.gridx = 0;
		gbc_massImport.gridy = 0;
		add(massImport, gbc_massImport);

		termBox = new JComboBox();
		termBox.setActionCommand("tb");

		GridBagConstraints gbc_termBox = new GridBagConstraints();
		gbc_termBox.insets = new Insets(0, 0, 5, 5);
		gbc_termBox.fill = GridBagConstraints.HORIZONTAL;
		gbc_termBox.gridx = 0;
		gbc_termBox.gridy = 1;
		add(termBox, gbc_termBox);

		deptScroll = new JScrollPane();
		GridBagConstraints gbc_deptScroll = new GridBagConstraints();
		gbc_deptScroll.fill = GridBagConstraints.BOTH;
		gbc_deptScroll.insets = new Insets(0, 0, 0, 5);
		gbc_deptScroll.gridx = 0;
		gbc_deptScroll.gridy = 2;
		add(deptScroll, gbc_deptScroll);

		JScrollPane adptScroll = new JScrollPane();
		GridBagConstraints gbc_adptScroll = new GridBagConstraints();
		gbc_adptScroll.gridwidth = 2;
		gbc_adptScroll.fill = GridBagConstraints.BOTH;
		gbc_adptScroll.gridx = 1;
		gbc_adptScroll.gridy = 2;
		add(adptScroll, gbc_adptScroll);

		adoptionTable = new JTable();
		adoptionTable.setAutoCreateRowSorter(true);
		adoptionTable.setFillsViewportHeight(true);
		adoptionTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
		adoptionTable.setModel(emptyTable());
		adptScroll.setViewportView(adoptionTable);

		termBox.addActionListener(aal);
		addComponentListener(aal);
		// aal.actionPerformed(null);
	}

	public void initTreeData() {
		Util.Util.printStatusString("initTreeData");

		tree = new CourseSectionTree();
		deptScroll.setViewportView(tree);
		tree.setShowsRootHandles(true);
		tree.expandRow(0);
		tree.setRootVisible(false);
		// tree.makeVisible(tree.getAnchorSelectionPath());

		for (Department d : inv.getDeptsOrdered()) {
			// Util.Util.printStatusString("tree: dept "+d.getCode().getCode());
			tree.addDept(d);
			// Util.Util.printStatusString("finished dept "+d.getCode().getCode()+"\n");
		}

		tree.makeVisible(new TreePath(tree.getModel().getRoot().getNextNode().getPath()));
		tree.addTreeSelectionListener(new SelectionListener());
		// Util.Util.printStatusString(String.valueOf(tree.getModel().getRoot().getChildCount()));
	}

	private DefaultTableModel emptyTable() {
		DefaultTableModel dtm = new DefaultTableModel(new Object[][] { { null,
				null, null, null, null }, }, new String[] { "Author", "Title",
				"Status", "ISBN", "Inv Num" }) {
			Class[] columnTypes = new Class[] { String.class, String.class,
					String.class, String.class, String.class };

			@Override
			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}
		};

		return dtm;
	}

	private class SelectionListener implements TreeSelectionListener {

		@Override
		public void valueChanged(TreeSelectionEvent arg0) {
			Util.Util.printStatusString("valueChanged fired!");
			// TODO Auto-generated method stub
			DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
					.getLastSelectedPathComponent();

			// nothing selected
			if (node == null) {
				Util.Util.printStatusString("valueChanged null");
				return;
			}
			
			adoptionTable.setModel(emptyTable());
			DefaultTableModel adoptionData = (DefaultTableModel) adoptionTable
					.getModel();
			adoptionData.removeRow(0); // remove blank row.

			if (node instanceof DepartmentNode) {
				Util.Util.printStatusString("valueChanged department!");
				return;
			}
			if (node instanceof CourseNode) {
				Util.Util.printStatusString("valueChanged course");
				return;
			}
			if (node instanceof SectionNode) {
				Util.Util.printStatusString("valueChanged section");
				Section sec = ((SectionNode) node).getSec();
				ArrayList<Adoption> adpts = sec.getAdoptions();
				Collections.sort(adpts);
				for (Adoption a : adpts) {
					Util.Util.printStatusString("valueChanged adoption");
					adoptionData.addRow(new String[] { a.getBook().getAuthor(),
							a.getBook().getTitle(), a.getStatus(),
							String.valueOf(a.getBook().getISBN()),
							a.getBook().getInv_num() });
				}
			}
			
			Util.Util.printStatusString("valueChanged idkwtf the node is!");

		}

	}

	private class CourseSectionTree extends JTree {

		public CourseSectionTree() {
			super();

			setModel(new CourseSectionTreeModel());
		}

		public void addDept(Department d) {
			getModel().addDept(d);
		}

		@Override
		public CourseSectionTreeModel getModel() {
			return (CourseSectionTreeModel) super.getModel();
		}

		public DefaultMutableTreeNode getRoot() {
			return getModel().getRoot();
		}
	}

	private class DepartmentNode extends DefaultMutableTreeNode {

		private Department dept;

		public DepartmentNode(Department d) {
			super(d.toString());

			dept = d;

			Collection<Course> crs = dept.getCoursesOrdered();
			if (crs.isEmpty())
				addEmptyCourse();
			else
				for (Course c : crs)
					addCourse(c);
		}

		public Department getDept() {
			return dept;
		}

		public String getText() {
			return toString();
		}

		private CourseNode addCourse(Course crs) {
			// Util.Util.printStatusString("tree: course "+crs.getNumber());
			CourseNode cn;
			add(cn = new CourseNode(crs));
			// Util.Util.printStatusString("finished: course "+crs.getNumber());
			return cn;
		}
		
		private void addEmptyCourse() {
			add(new CourseNode());
		}
	}

	private class CourseNode extends DefaultMutableTreeNode {
		private Course crs;

		public CourseNode(Course c) {
			super(c.getNumber());

			crs = c;

			Collection<Section> secs = crs.getSectionsOrdered();
			
			if (secs.isEmpty())
				addEmptySection();
			else
				for (Section s : secs)
					addSection(s);
		}
		
		public CourseNode() {
			super("No Courses");
		}

		public Course getCrs() {
			return crs;
		}

		public String getText() {
			return toString();
		}

		private void addSection(Section s) {
			// Util.Util.printStatusString("tree: section "+s.getID());
			add(new SectionNode(s));
			// Util.Util.printStatusString("finished: section "+s.getID());
		}
		
		private void addEmptySection() {
			add(new SectionNode());
		}
	}

	private class SectionNode extends DefaultMutableTreeNode {
		private Section sec;

		public SectionNode(Section s) {
			super(s.getID());

			sec = s;
		}
		
		public SectionNode() {
			super("No Sections");
		}

		public Section getSec() {
			return sec;
		}

		public String getText() {
			return toString();
		}

	}

	private class CourseSectionTreeModel extends DefaultTreeModel {

		private DefaultMutableTreeNode root;

		public CourseSectionTreeModel() {
			super(new DefaultMutableTreeNode("depts"));
			root = getRoot();
		}

		@Override
		public DefaultMutableTreeNode getRoot() {
			return (DefaultMutableTreeNode) super.getRoot();
		}

		public DepartmentNode addDept(Department d) {
			DepartmentNode dn;
			root.add(dn = new DepartmentNode(d));
			return dn;
		}
	}

	private class AdoptionActionListener implements ActionListener,
			ComponentListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {

			if (arg0 != null
					&& arg0.getActionCommand().equalsIgnoreCase("import")) {
				AdoptionImport ai = new AdoptionImport(inv, this);
				ai.setVisible(true);
				return;
			}
			
			if (arg0.getActionCommand().equalsIgnoreCase("tb")) {
				Term sel = (Term)termBox.getSelectedItem(),
					 cur = inv.getCurTerm();
				
				if (sel.compareTo(cur) != 0)
					selectTerm(sel);
			}
		}
		
		private void selectTerm(Term t) {
			inv.selectTerm(t);
			initTreeData();
		}

		private DefaultComboBoxModel getCourses(Code selected) {

			curDept = inv.getCurTerm().getDept(selected);

			Map<Integer, Course> courseMap = curDept.getCourses();
			Course[] courseArray;
			if (courseMap.isEmpty()) {
				courseArray = new Course[] { null };
			} else {
				int i = 0;
				courseArray = new Course[courseMap.size()];
				List<Integer> crsList = new ArrayList<Integer>(
						courseMap.keySet());
				Collections.sort(crsList);
				for (Integer crsNum : crsList)
					courseArray[i++] = courseMap.get(crsNum);
			}
			return new DefaultComboBoxModel(courseArray);
		}

		private DefaultComboBoxModel getSections(Course selected) {

			// set course number label
			curCourse = selected;

			Map<String, Section> secs = curCourse.getSections();
			Section[] sectionArray;

			if (secs.isEmpty())
				sectionArray = new Section[] { null };
			else {
				sectionArray = new Section[secs.size()];
				List<String> secList = new ArrayList<String>(secs.keySet());
				Collections.sort(secList);
				int i = 0;
				for (String s : secList)
					sectionArray[i++] = secs.get(s);
			}

			return new DefaultComboBoxModel(sectionArray);
		}

		private void getAdoptions(Section selected) {

			if (curSection == null || curSection != selected) {
				// retrieve adoptions
				curSection = selected;
				List<Adoption> adoptions = curSection.getAdoptions();

				if (adoptions.isEmpty())
					return;
				else {
					DefaultTableModel adoptionData = (DefaultTableModel) adoptionTable
							.getModel();
					for (; 0 < adoptionData.getRowCount();)
						adoptionData.removeRow(0);
					for (Adoption a : adoptions)
						adoptionData.addRow(new String[] {
								a.getBook().getAuthor(),
								a.getBook().getTitle(), a.getStatus(),
								String.valueOf(a.getBook().getISBN()),
								a.getBook().getInv_num() });
				}
			}
		}

		@Override
		public void componentHidden(ComponentEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public void componentMoved(ComponentEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public void componentResized(ComponentEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public void componentShown(ComponentEvent e) {
			termBox.setModel(new DefaultComboBoxModel(inv.initTerms()));
			initTreeData();
		}

	}
}
